
Perl open file
Opening files is straightforward in Perl. Files must be opened and closed using - wait for it - the commands 'open' and 'close'. You should be careful to close files after you have finished with them - especially if you are writing to a file. Files are buffered and often large parts of a file are not actually written until the 'close' command is received.
Three files are , of course, always open for every program, namely `STDIN', 'STDOUT' and `STDERR'
Formally, to open a file, we must obtain a file descriptor or file handle. This is done using `open;
open (file_descrip, "Filename") ;
The angular brackets '<...>' are used to read from the file. For example.
$line <file_descrip>;
reads one line from the file associated with 'file_descrip'.
Let's look at some examples of filing opening. Hese is how we can implement UNIX's 'cut' and 'paste' commands in perl:
#!/local/bin/perl
#cut in perl
#cut second column
while (<>)
{
@cut_array = split;
print "@cut _array [l] \ n" ;
}
This is the simplest way to open a file. The empty file descriptor `<>' tells peal to take the argument of the command as a filename and open that file for reading. This is really short for 'while($_=<STDIN>)' with the standard input redirected to the named file.
The `paste' program can be written as
#!/local/bin/perl
# Paste in perl
# Two files only, syntax : paste file lfile2
open (filel,"@ARGV [0] ") || die "Can't open @ARGV [0] \n";
open (file2,"@ARGV Eli") || die "Can't open @ARGV[1] \n";
while (($linel=<file1>) || ($line2=<file2>))
{
chop $linel;
chop $line2;
print "$linel $line2\n"; # tab character between
}
Here we see more formally how to read from two separate files at the same time. Notice that, by putting the read commands into the test-expression for the 'while' loop, we are using the fact that ‘<….>’ returns a non-zero (true) value unless we have readied the end of the file.
#!/local/bin/perl
open (HANDLE,"$ARGV[1]");
while (<HANDLE>)
{
print $_ ;
}
Here we have simply filled in the assumptions explicitly. The command '<HANDLE>' now reads a single line from the named file-handle into the default variable `C. To make this program more general, we can eliminate the defaults entirely.
#!/local/bin/perl
open (HANDLE,"$ARGV[1]");
while($line=<HANDLE>)
{
Print $line;
}
== and ‘eq’
Be careful to distinguish between the comparison operator for integers and the corresponding operator for strings 'eq%' These do not work in each other's places so if you get the wrong comparison operator your program might not work and it is quite difficult to find the error.
Perl chop
The command 'chop' cuts off the last character of a string. This is useful for removing; newline characters when reading files etc. The syntax is
chop; # chop $_ ;
chop $scalar; # remove last character in $scalar
Perl subroutine
Subroutines are indicated, as in the example above, by the ampersand ‘&’ symbol. When parameters are passed to a Perl subroutine, they are handed over as an array called '@_'. Which is analogous to the `$_' variable. Here is a simple example:
#!/local/bin/perl
$a="silver";
$b="gold";
&PrintArgs($a,$b);
# end of main
sub PrintArgs
{
($local_a,$local_b) = 0_;
print "$local_a, $local_b\n";
}
Perl die - exit on perl error
When a program has to quit and give a message, the 'die' command is normally used. If called without an argument, Pen generates its own message including a line number at which the error occurred. 'lb include your own message, you write
die "My message....";
If the string is terminated with a ‘\n' newline character, the line number of the error is not printed, otherwise Perl appends the line number to your string.
When opening files, it is common to see the syntax:
open (filehandle,"Filename") II die "Can't open...";
The logical 'OR' symbol is used, because 'open' returns true if all goes well, in which case the right hand side is never evaluated. If 'open' is false, then die is executed. You can decide for yourself whether or not you think this is good programming style - we mention it here because it is common practice.
The stat() idiom
The UNIX library function stat () is used to find out information about a given file. This function is available both in C and in Perl. In per], it returns an array of values. Usually we are interested in knowing the access permissions of a file. stat() is called using: the syntax
@array = stat ("filename");
or alternatively, using a named array
($device,$inode,$mode) = stat("filename");
The value returned in the mode variable is a bit-pattern, See (undefined) [Protection bits], page (undefined). The most useful way of treating these hit patterns is to use octal numbers to interpret their meaning.
For example, to test whether a file is writable to other users in the same group as the file, we would write the following.
$mask = 020; # Leading 0 means octal number
($device,$inode,$mode) = stat("file");
if ($mode & $mask)
{
print "File is writable by the group\n";
}
Here the 2 in the second octal number means "write", the fact that it is the second octal number from the right means that it refers to "group". Thus the result of the if-test is only true if that particular bit is true. We shall see this idiom in action below.
The passwd program and 'crypt ()' function
Here is a simple implementation of the UNIX 'passwd. program in Perl.
# A perl version of the passwd program.
# Note - the real passwd program needs to be much more
#secure than this one. This is just to demonstrate the
#use of the crypt() function.
#!/local/bin/perl
print "Changing passwd for $ENV{'USER'} on $ENV{'HOST'}\n";
system 'stty','-echo';
print "Old passwd: ";
$oldpwd = <STDIN> ;
chop $oldpwd;
($name,$coded_pwd,$uid,$gid,$x,$y,$z,$gcos,$home,$shell)= getpwnam($ENV{"USER"});
if (crypt($oldpwd,$coded_pwd) ne $coded_pwd)
{
print "\nPasswd incorrect\n";
exit (1);
}
$oldpwd = ""; #destroy the evidence!
print "\nNew passwd: ";
$newpwd = <STDIN>;
print "\nRepeat new passwd: ";
$rnewpwd = <STDIN>;
chop $newpwd;
chop $rnewpwd;
if ($newpwd ne $rnewpwd)
{
print "\n Incorrectly typed. Password unchanged.\n";
exit (1);
}
$salt = rand();
$new_coded_pwd = crypt($newpwd,$salt);
print"\n\n$name:Snew_coded_pwd:$uid:$gid:$gcos:$home:$shell/\n";